package server;




import java.io.IOException;
import java.net.BindException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.util.Iterator;
import java.util.Set;

import lp.polimi.treefinder.utils.ManagingMessage;


public class DefaultSingleProtocol implements SingleProtocol {


	protected boolean initialized = false;

	protected Server server = Server.getSharedInstance();
	protected int port;

	protected ServerSocket socket;
	protected InetAddress addr;



	public DefaultSingleProtocol (int port) {
		this.port = port;
	}

	@Override
	public void initialize() {
		if (initialized == false) {
			try {
				addr = InetAddress.getLocalHost();
				socket = new ServerSocket(port);
			} catch (BindException e) {
				e.printStackTrace();
				server.getFeedbackManager().printErrorAndExit("Unable binding server socket. Process will be terminated.");
			} catch (Exception e) {
				e.printStackTrace();
				server.getFeedbackManager().printErrorAndExit("Error while initializing TCP Protocol. Process will be terminated.");

			}
			initialized = true;
		}
	}

	@Override
	public void writeInfo() {
		server.getFeedbackManager().printInfoMessage("IP: "+addr);
		server.getFeedbackManager().printInfoMessage("Port: "+socket.getLocalPort());
		server.getFeedbackManager().printInfoMessage("Host Name: "+addr.getHostName());
	}


	@Override
	public void send(ManagingMessage managingMessage, Object address) throws IOException {
		((Connection)server.getUsersManager().getUser((String)address).getProperty("connectionThread")).send(managingMessage);
	}

	@Override
	public void closeSocket(Object address) {
		((Connection)server.getUsersManager().getUser((String) address).getProperty("connectionThread")).closeSocket();
	}

	@Override
	public void closeSockets() {
		Set<String> currentUsers = server.getUsersManager().getUsers().keySet();
		Iterator<String> it = currentUsers.iterator();
		while (it.hasNext()) {
			((Connection)server.getUsersManager().getUser(it.next()).getProperty("connectionThread")).closeSocket();
		}

	}

	@Override
	public InetAddress getAddress() {
		return socket.getInetAddress();
	}

	@Override
	public int getPort() {
		return socket.getLocalPort();
	}


	@Override
	public GenericSocket acceptConnection() throws IOException {
		return new DefaultTCPSocket(socket.accept());
	}



}
